#include "silksource.h"

/* Define codec specific settings */
#define MAX_BYTES_ENC_PER_FRAME     250 // Equals peak bitrate of 100 kbps
#define MAX_BYTES_DEC_PER_FRAME     1024

#define MAX_INPUT_FRAMES        5
#define MAX_LBRR_DELAY          2
#define MAX_FRAME_LENGTH        480

#define	MAX_FRAME			320

SilkSource::SilkSource():
    mInFile(NULL),
    mSilkDec(NULL)
{
}

SilkSource::~SilkSource()
{
    if(mInFile){
        fclose(mInFile);
        mInFile = NULL;
    }
    if(mSilkDec){
        free(mSilkDec);
        mSilkDec = NULL;
    }
}

int SilkSource::init(char *src)
{
    int ret = 0;
    SKP_int32 decSizeBytes;
    if(src == NULL){
        printf("%s src is null\n", __FUNCTION__);
        return -1;
    }
    mInFileName = src;
    mInFile = fopen(src, "rb");
    if( mInFile == NULL ) {
        printf( "Error: could not open input file %s\n", src);
        return -1;
    }

    if(check_header()){
        printf("silk header error\n");
        return -1;
    }

    mDecControl.sampleRate = 16000;

    /* Create decoder */
    ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );
    if(ret){
        printf("error:SKP_Silk_SDK_Get_Decoder_Size\n");
        return ret;
    }
    mSilkDec = malloc( decSizeBytes );

    ret = SKP_Silk_SDK_InitDecoder( mSilkDec );
    if( ret ) {
        printf( "error:SKP_Silk_InitDecoder returned %d\n", ret );
        free(mSilkDec);
        mSilkDec = NULL;
        return ret;
    }
    return 0;
}

int SilkSource::check_header()
{
    const char SILKHEADER[] = "\x02#!SILK_V3";
    int counter = 0;

    if(mInFile == NULL)
        return -1;

    char header_buf[sizeof(SILKHEADER)];
    counter = fread( header_buf, sizeof( char ), strlen(SILKHEADER), mInFile );
    if(counter == strlen(SILKHEADER) && !memcmp( header_buf, SILKHEADER, strlen(SILKHEADER))) {
        return 0;
    }
    return 1;
}

/*
 * O:frame:decoded frame
 * O:size:length
 * ret: 0:OK
*/
int SilkSource::decode_apacket(uint8_t *frame, int *size)
{
    int counter = -1;
    SKP_int16 nBytes;
    SKP_uint8 payload[MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
    SKP_int16 len = 0;
    int ret;

    *size = 0;

    counter = fread( &nBytes, sizeof( SKP_int16 ), 1, mInFile );
    //nBytes = EXTRACT_16BITS(&nBytes);
    if( nBytes < 0 || counter < 1 ) {
        return -1;
    }

    /* Read payload */
    counter = fread( payload, sizeof( SKP_uint8 ), nBytes, mInFile );
    if( ( SKP_int16 )counter < nBytes ) {
        printf("%s:expected %d but ret %d\n", __FUNCTION__, nBytes, counter);
        return -1;
    }

    do {
        /* Decode 20 ms */
        ret = SKP_Silk_SDK_Decode( mSilkDec, &mDecControl, 0, payload, nBytes, (SKP_int16 *)frame, &len );
        if( ret ) {
            printf( "error:SKP_Silk_SDK_Decode returned %d\n", ret );
        }

        //printf("frame size :%d/%d :%d\n", mDecControl.frameSize, mDecControl.framesPerPacket, mDecControl.inBandFECOffset);
        frame += len;
        *size += len;
    } while( mDecControl.moreInternalDecoderFrames );

    return 0;
}
